home *** CD-ROM | disk | FTP | other *** search
/ Die Speccy' 97 / Die Speccy' 97.iso / amiga_system / the_aminet / comm / bbs / wwbbs31_source.lha / Hydra / hydra.c < prev    next >
C/C++ Source or Header  |  1994-06-28  |  88KB  |  2,008 lines

  1. /*=============================================================================
  2.  
  3.                               HydraCom Version 1.00
  4.  
  5.                          A sample implementation of the
  6.                    HYDRA Bi-Directional File Transfer Protocol
  7.  
  8.                              HydraCom was written by
  9.                    Arjen G. Lentz, LENTZ SOFTWARE-DEVELOPMENT
  10.                   COPYRIGHT (C) 1991-1993; ALL RIGHTS RESERVED
  11.  
  12.                        The HYDRA protocol was designed by
  13.                  Arjen G. Lentz, LENTZ SOFTWARE-DEVELOPMENT and
  14.                              Joaquim H. Homrighausen
  15.                   COPYRIGHT (C) 1991-1993; ALL RIGHTS RESERVED
  16.  
  17.  
  18.   Revision history:
  19.   06 Sep 1991 - (AGL) First tryout
  20.   .. ... .... - Internal development
  21.   11 Jan 1993 - HydraCom version 1.00, Hydra revision 001 (01 Dec 1992)
  22.  
  23.  
  24.   For complete details of the Hydra and HydraCom licensing restrictions,
  25.   please refer to the license agreements which are published in their entirety
  26.   in HYDRACOM.C and LICENSE.DOC, and also contained in the documentation file
  27.   HYDRACOM.DOC
  28.  
  29.   Use of this file is subject to the restrictions contained in the Hydra and
  30.   HydraCom licensing agreements. If you do not find the text of this agreement
  31.   in any of the aforementioned files, or if you do not have these files, you
  32.   should immediately contact LENTZ SOFTWARE-DEVELOPMENT and/or Joaquim 
  33.   Homrighausen at one of the addresses listed below. In no event should you
  34.   proceed to use this file without having accepted the terms of the Hydra and
  35.   HydraCom licensing agreements, or such other agreement as you are able to
  36.   reach with LENTZ SOFTWARE-DEVELOMENT and Joaquim Homrighausen.
  37.  
  38.  
  39.   Hydra protocol design and HydraCom driver:         Hydra protocol design:
  40.   Arjen G. Lentz                                     Joaquim H. Homrighausen
  41.   LENTZ SOFTWARE-DEVELOPMENT                         389, route d'Arlon
  42.   Langegracht 7B                                     L-8011 Strassen
  43.   3811 BT  Amersfoort                                Luxembourg
  44.   The Netherlands
  45.   FidoNet 2:283/512, AINEX-BBS +31-33-633916         FidoNet 2:270/17
  46.   arjen_lentz@f512.n283.z2.fidonet.org               joho@ae.lu
  47.  
  48.   Please feel free to contact us at any time to share your comments about our
  49.   software and/or licensing policies.
  50.  
  51. =============================================================================*/
  52.  
  53. #include "hydracom.h"                             /* need 2types.h & hydra.h */
  54.  
  55. #ifdef AMIGA
  56. #include <dos/dos.h>
  57. #include <clib/dos_protos.h>
  58. #endif    /* AMIGA */
  59.  
  60. #define H_DEBUG 1
  61.  
  62.  
  63. /* HYDRA Some stuff to aid readability of the source and prevent typos ----- */
  64. #define h_updcrc16(crc,c)  (crc16tab[(       crc ^ (c)) & 0xff] ^ ((crc >> 8) & 0x00ff))
  65. #define h_updcrc32(crc,c)  (crc32tab[((byte) crc ^ (c)) & 0xff] ^ ((crc >> 8) & 0x00ffffffL))
  66. #define h_crc16poly        (0x8408)
  67. #define h_crc32poly        (0xedb88320L)
  68. #define h_crc16test(crc)   (((crc) == 0xf0b8     ) ? 1 : 0)
  69. #define h_crc32test(crc)   (((crc) == 0xdebb20e3L) ? 1 : 0)
  70. #define h_uuenc(c)         (((c) & 0x3f) + '!')
  71. #define h_uudec(c)         (((c) - '!') & 0x3f)
  72. #define h_long1(buf)       (*((long *) (buf)))
  73. #define h_long2(buf)       (*((long *) ((buf) + ((int) sizeof (long)))))
  74. #define h_long3(buf)       (*((long *) ((buf) + (2 * ((int) sizeof (long))))))
  75. typedef long               h_timer;
  76. #define h_timer_set(t)     (time(NULL) + (t))
  77. #define h_timer_running(t) (t != 0L)
  78. #define h_timer_expired(t) (time(NULL) > (t))
  79. #define h_timer_reset()    (0L)
  80.  
  81.  
  82. /* HYDRA's memory ---------------------------------------------------------- */
  83. static  boolean originator;                     /* are we the orig side?     */
  84. static  int     batchesdone;                    /* No. HYDRA batches done    */
  85. static  boolean hdxlink;                        /* hdx link & not orig side  */
  86. static  dword   options;                        /* INIT options hydra_init() */
  87. static  word    timeout;                        /* general timeout in secs   */
  88. static  char    abortstr[] = { 24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0 };
  89. static  char   *hdxmsg     = "Fallback to one-way xfer";
  90. static  char   *pktprefix  = "";
  91. static  char   *autostr    = "hydra\r";
  92. static  word   *crc16tab;                       /* CRC-16 table              */
  93. static  dword  *crc32tab;                       /* CRC-32 table              */
  94.  
  95. static  byte   *txbuf,         *rxbuf;          /* packet buffers            */
  96. static  dword   txoptions,      rxoptions;      /* HYDRA options (INIT seq)  */
  97. static  char    txpktprefix[H_PKTPREFIX + 1];   /* pkt prefix str they want  */
  98. static  long    txwindow,       rxwindow;       /* window size (0=streaming) */
  99. static  h_timer                 braindead;      /* braindead timer           */
  100. static  byte   *txbufin;                        /* read data from disk here  */
  101. static  byte    txlastc;                        /* last byte put in txbuf    */
  102. static  byte                    rxdle;          /* count of received H_DLEs  */
  103. static  byte                    rxpktformat;    /* format of pkt receiving   */
  104. static  byte                   *rxbufptr;       /* current position in rxbuf */
  105. static  byte                   *rxbufmax;       /* highwatermark of rxbuf    */
  106. static  char    txfname[108],    rxfname[108];    /* fname of current files    */
  107. static  char                   *rxpathname;     /* pointer to rx pathname    */
  108. static  long    txftime,        rxftime;        /* file timestamp (UNIX)     */
  109. static  long    txfsize,        rxfsize;        /* file length               */
  110. static  int     txfd,           rxfd;           /* file handles              */
  111. static  word                    rxpktlen;       /* length of last packet     */
  112. static  word                    rxblklen;       /* len of last good data blk */
  113. static  byte    txstate,        rxstate;        /* xmit/recv states          */
  114. static  long    txpos,          rxpos;          /* current position in files */
  115. static  word    txblklen;                       /* length of last block sent */
  116. static  word    txmaxblklen;                    /* max block length allowed  */
  117. static  long    txlastack;                      /* last dataack received     */
  118. static  long    txstart,        rxstart;        /* time we started this file */
  119. static  long    txoffset,       rxoffset;       /* offset in file we begun   */
  120. static  h_timer txtimer,        rxtimer;        /* retry timers              */
  121. static  word    txretries,      rxretries;      /* retry counters            */
  122. static  long                    rxlastsync;     /* filepos last sync retry   */
  123. static  long    txsyncid,       rxsyncid;       /* id of last resync         */
  124. static  word    txgoodneeded;                   /* to send before larger blk */
  125. static  word    txgoodbytes;                    /* no. sent at this blk size */
  126.  
  127. struct _h_flags {
  128.         char  *str;
  129.         dword  val;
  130. };
  131.  
  132. static struct _h_flags h_flags[] = {
  133.         { "XON", HOPT_XONXOFF },
  134.         { "TLN", HOPT_TELENET },
  135.         { "CTL", HOPT_CTLCHRS },
  136.         { "HIC", HOPT_HIGHCTL },
  137.         { "HI8", HOPT_HIGHBIT },
  138.         { "BRK", HOPT_CANBRK  },
  139.         { "ASC", HOPT_CANASC  },
  140.         { "UUE", HOPT_CANUUE  },
  141.         { "C32", HOPT_CRC32   },
  142.         { "DEV", HOPT_DEVICE  },
  143.         { "FPT", HOPT_FPT     },
  144.         { NULL , 0x0L         }
  145. };
  146.  
  147.  
  148. /*---------------------------------------------------------------------------*/
  149. static void hydra_msgdev (byte *data, word len)
  150. {       /* text is already NUL terminated by calling func hydra_devrecv() */
  151.         len = len;
  152.         message(3,"*HMSGDEV: %s",data);
  153. }/*hydra_msgdev()*/
  154.  
  155.  
  156. /*---------------------------------------------------------------------------*/
  157. static  word    devtxstate;                     /* dev xmit state            */
  158. static  h_timer devtxtimer;                     /* dev xmit retry timer      */
  159. static  word    devtxretries;                   /* dev xmit retry counter    */
  160. static  long    devtxid,        devrxid;        /* id of last devdata pkt    */
  161. static  char    devtxdev[H_FLAGLEN + 1];        /* xmit device ident flag    */
  162. static  byte   *devtxbuf;                       /* ptr to usersupplied dbuf  */
  163. static  word    devtxlen;                       /* len of data in xmit buf   */
  164.  
  165. struct _h_dev {
  166.         char  *dev;
  167.         void (*func) (byte *data, word len);
  168. };
  169.  
  170. static  struct _h_dev h_dev[] = {
  171.         { "MSG", hydra_msgdev },                /* internal protocol msg     */
  172.         { "CON", NULL         },                /* text to console (chat)    */
  173.         { "PRN", NULL         },                /* data to printer           */
  174.         { "ERR", NULL         },                /* text to error output      */
  175.         { NULL , NULL         }
  176. };
  177.  
  178.  
  179. /*---------------------------------------------------------------------------*/
  180. boolean hydra_devfree (void)
  181. {
  182.         if (devtxstate || !(txoptions & HOPT_DEVICE) || txstate >= HTX_END)
  183.            return (false);                      /* busy or not allowed       */
  184.         else
  185.            return (true);                       /* allowed to send a new pkt */
  186. }/*hydra_devfree()*/
  187.  
  188.  
  189. /*---------------------------------------------------------------------------*/
  190. boolean hydra_devsend (char *dev, byte *data, word len)
  191. {
  192.         if (!dev || !data || !len || !hydra_devfree())
  193.            return (false);
  194.  
  195.         strncpy(devtxdev,dev,H_FLAGLEN);
  196.         devtxdev[H_FLAGLEN] = '\0';
  197. #ifndef AMIGA
  198.         strupr(devtxdev);
  199. #endif    /* AMIGA */
  200.         devtxbuf = data;
  201.         devtxlen = (len > H_MAXBLKLEN) ? H_MAXBLKLEN : len;
  202.  
  203.         devtxid++;
  204.         devtxtimer   = h_timer_reset();
  205.         devtxretries = 0;
  206.         devtxstate   = HTD_DATA;
  207.  
  208.         /* special for chat, only prolong life if our side keeps typing! */
  209.         if (chattimer > 0L && !strcmp(devtxdev,"CON") && txstate == HTX_REND)
  210.            braindead = h_timer_set(H_BRAINDEAD);
  211.  
  212.         return (true);
  213. }/*hydra_devsend()*/
  214.  
  215.  
  216. /*---------------------------------------------------------------------------*/
  217. boolean hydra_devfunc (char *dev, void (*func) (byte *data, word len))
  218. {
  219.         register int i;
  220.  
  221.         for (i = 0; h_dev[i].dev; i++) {
  222.             if (!strnicmp(dev,h_dev[i].dev,H_FLAGLEN)) {
  223.                h_dev[i].func = func;
  224.                return (true);
  225.             }
  226.         }
  227.  
  228.         return (false);
  229. }/*hydra_devfunc()*/
  230.  
  231.  
  232. /*---------------------------------------------------------------------------*/
  233. static void hydra_devrecv (void)
  234. {
  235.         register char *p = (char *) rxbuf;
  236.         register int   i;
  237.         word len = rxpktlen;
  238.  
  239.         p += (int) sizeof (long);                       /* skip the id long  */
  240.         len -= (int) sizeof (long);
  241.         for (i = 0; h_dev[i].dev; i++) {                /* walk through devs */
  242.             if (!strncmp(p,h_dev[i].dev,H_FLAGLEN)) {
  243.                if (h_dev[i].func) {
  244.                   len -= ((int) strlen(p)) + 1;         /* sub devstr len    */
  245.                   p += ((int) strlen(p)) + 1;           /* skip devtag       */
  246.                   p[len] = '\0';                        /* NUL terminate     */
  247.                   (*h_dev[i].func)((byte *) p,len);     /* call output func  */
  248.                }
  249.                break;
  250.             }
  251.         }
  252. }/*hydra_devrecv()*/
  253.  
  254.  
  255. /*---------------------------------------------------------------------------*/
  256. static void put_flags (char *buf, struct _h_flags flags[], long val)
  257. {
  258.         register char *p;
  259.         register int   i;
  260.  
  261.         p = buf;
  262.         for (i = 0; flags[i].val; i++) {
  263.             if (val & flags[i].val) {
  264.                if (p > buf) *p++ = ',';
  265.                strcpy(p,flags[i].str);
  266.                p += H_FLAGLEN;
  267.             }
  268.         }
  269.         *p = '\0';
  270. }/*put_flags()*/
  271.  
  272.  
  273. /*---------------------------------------------------------------------------*/
  274. static dword get_flags (char *buf, struct _h_flags flags[])
  275. {
  276.         register dword  val;
  277.         register char  *p;
  278.         register int    i;
  279.  
  280.         val = 0x0L;
  281.         for (p = strtok(buf,","); p; p = strtok(NULL,",")) {
  282.             for (i = 0; flags[i].val; i++) {
  283.                 if (!strcmp(p,flags[i].str)) {
  284.                    val |= flags[i].val;
  285.                    break;
  286.                 }
  287.             }
  288.         }
  289.  
  290.         return (val);
  291. }/*get_flags()*/
  292.  
  293.  
  294. /*---------------------------------------------------------------------------*/
  295. static word crc16block (register byte *buf, register word len)
  296. {
  297.         register word crc;
  298.  
  299.         for (crc = 0xffff; len > 0; len--)
  300.             crc = h_updcrc16(crc,*buf++);
  301.         return (crc);
  302. }/*crc16block()*/
  303.  
  304.  
  305. /*---------------------------------------------------------------------------*/
  306. static dword crc32block (register byte *buf, register word len)
  307. {
  308.         register dword crc;
  309.  
  310.         for (crc = 0xffffffffL; len > 0; len--)
  311.             crc = h_updcrc32(crc,*buf++);
  312.         return (crc);
  313. }/*crc32block()*/
  314.  
  315.  
  316. /*---------------------------------------------------------------------------*/
  317. static byte *put_binbyte (register byte *p, register byte c)
  318. {
  319.         register byte n;
  320.  
  321.         n = c;
  322.         if (txoptions & HOPT_HIGHCTL)
  323.            n &= 0x7f;
  324.  
  325.         if (n == H_DLE ||
  326.             ((txoptions & HOPT_XONXOFF) && (n == XON || n == XOFF)) ||
  327.             ((txoptions & HOPT_TELENET) && n == '\r' && txlastc == '@') ||
  328.             ((txoptions & HOPT_CTLCHRS) && (n < 32 || n == 127))) {
  329.            *p++ = H_DLE;
  330.            c ^= 0x40;
  331.         }
  332.  
  333.         *p++ = c;
  334.         txlastc = n;
  335.  
  336.         return (p);
  337. }/*put_binbyte()*/
  338.  
  339.  
  340. /*---------------------------------------------------------------------------*/
  341. static void txpkt (register word len, int type)
  342. {
  343.         register byte *in, *out;
  344.         register word  c, n;
  345.         boolean crc32 = false;
  346.         byte    format;
  347.         static char hexdigit[] = "0123456789abcdef";
  348.  
  349.         txbufin[len++] = type;
  350.  
  351.         switch (type) {
  352.                case HPKT_START:
  353.                case HPKT_INIT:
  354.                case HPKT_INITACK:
  355.                case HPKT_END:
  356.                case HPKT_IDLE:
  357.                     format = HCHR_HEXPKT;
  358.                     break;
  359.  
  360.                default:
  361.                     /* COULD do smart format selection depending on data and options! */
  362.                     if (txoptions & HOPT_HIGHBIT) {
  363.                        if ((txoptions & HOPT_CTLCHRS) && (txoptions & HOPT_CANUUE))
  364.                           format = HCHR_UUEPKT;
  365.                        else if (txoptions & HOPT_CANASC)
  366.                           format = HCHR_ASCPKT;
  367.                        else
  368.                           format = HCHR_HEXPKT;
  369.                     }
  370.                     else
  371.                        format = HCHR_BINPKT;
  372.                     break;
  373.         }
  374.  
  375.         if (format != HCHR_HEXPKT && (txoptions & HOPT_CRC32))
  376.            crc32 = true;
  377.  
  378. #if H_DEBUG
  379. if (loglevel==0) {
  380.    char *s1, *s2, *s3, *s4;
  381.  
  382.    message(0," -> PKT (format='%c'  type='%c'  crc=%d  len=%d)",
  383.              format, type, crc32 ? 32 : 16, len - 1);
  384.  
  385.    switch (type) {
  386.           case HPKT_START:    message(0,"    <autostr>START");
  387.                               break;
  388.           case HPKT_INIT:     s1 = ((char *) txbufin) + ((int) strlen((char *) txbufin)) + 1;
  389.                               s2 = s1 + ((int) strlen(s1)) + 1;
  390.                               s3 = s2 + ((int) strlen(s2)) + 1;
  391.                               s4 = s3 + ((int) strlen(s3)) + 1;
  392.                               message(0,"    INIT (appinfo='%s'  can='%s'  want='%s'  options='%s'  pktprefix='%s')",
  393.                                       (char *) txbufin, s1, s2, s3, s4);
  394.                               break;
  395.           case HPKT_INITACK:  message(0,"    INITACK");
  396.                               break;
  397.           case HPKT_FINFO:    message(0,"    FINFO (%s)",txbufin);
  398.                               break;
  399.           case HPKT_FINFOACK: if (rxfd >= 0) {
  400.                                  if (rxpos > 0L) s1 = "RES";
  401.                                  else            s1 = "BOF";
  402.                               }
  403.                               else if (rxpos == -1L) s1 = "HAVE";
  404.                               else if (rxpos == -2L) s1 = "SKIP";
  405.                               else                   s1 = "EOB";
  406.                               message(0,"    FINFOACK (pos=%ld %s  rxstate=%d  rxfd=%d)",
  407.                                       rxpos,s1,rxstate,rxfd);
  408.                               break;
  409.           case HPKT_DATA:     message(0,"    DATA (ofs=%ld  len=%d)",
  410.                                       intell(h_long1(txbufin)), len - 5);
  411.                               break;
  412.           case HPKT_DATAACK:  message(0,"    DATAACK (ofs=%ld)",
  413.                                       intell(h_long1(txbufin)));
  414.                               break;
  415.           case HPKT_RPOS:     message(0,"    RPOS (pos=%ld%s  blklen=%ld  syncid=%ld)",
  416.                                       rxpos, rxpos < 0L ? " SKIP" : "",
  417.                                       intell(h_long2(txbufin)), rxsyncid);
  418.                               break;
  419.           case HPKT_EOF:      message(0,"    EOF (ofs=%ld%s)",
  420.                                       txpos, txpos < 0L ? " SKIP" : "");
  421.                               break;
  422.           case HPKT_EOFACK:   message(0,"    EOFACK");
  423.                               break;
  424.           case HPKT_IDLE:     message(0,"    IDLE");
  425.                               break;
  426.           case HPKT_END:      message(0,"    END");
  427.                               break;
  428.           case HPKT_DEVDATA:  message(0,"    DEVDATA (id=%ld  dev='%s'  len=%u)",
  429.                                       devtxid, devtxdev, devtxlen);
  430.                               break;
  431.           case HPKT_DEVDACK:  message(0,"    DEVDACK (id=%ld)",
  432.                                       intell(h_long1(rxbuf)));
  433.                               break;
  434.           default:            /* This couldn't possibly happen! ;-) */
  435.                               break;
  436.    }
  437. }
  438. #endif
  439.  
  440.         if (crc32) {
  441.            dword crc = ~crc32block(txbufin,len);
  442.  
  443.            txbufin[len++] = crc;
  444.            txbufin[len++] = crc >> 8;
  445.            txbufin[len++] = crc >> 16;
  446.            txbufin[len++] = crc >> 24;
  447.         }
  448.         else {
  449.            word crc = ~crc16block(txbufin,len);
  450.  
  451.            txbufin[len++] = crc;
  452.            txbufin[len++] = crc >> 8;
  453.         }
  454.  
  455.         in = txbufin;
  456.         out = txbuf;
  457.         txlastc = 0;
  458.         *out++ = H_DLE;
  459.         *out++ = format;
  460.  
  461.         switch (format) {
  462.                case HCHR_HEXPKT:
  463.                     for (; len > 0; len--, in++) {
  464.                         if (*in & 0x80) {
  465.                            *out++ = '\\';
  466.                            *out++ = hexdigit[((*in) >> 4) & 0x0f];
  467.                            *out++ = hexdigit[(*in) & 0x0f];
  468.                         }
  469.                         else if (*in < 32 || *in == 127) {
  470.                            *out++ = H_DLE;
  471.                            *out++ = (*in) ^ 0x40;
  472.                         }
  473.                         else if (*in == '\\') {
  474.                            *out++ = '\\';
  475.                            *out++ = '\\';
  476.                         }
  477.                         else
  478.                            *out++ = *in;
  479.                     }
  480.                     break;
  481.  
  482.                case HCHR_BINPKT:
  483.                     for (; len > 0; len--)
  484.                         out = put_binbyte(out,*in++);
  485.                     break;
  486.  
  487.                case HCHR_ASCPKT:
  488.                     for (n = c = 0; len > 0; len--) {
  489.                         c |= ((*in++) << n);
  490.                         out = put_binbyte(out,c & 0x7f);
  491.                         c >>= 7;
  492.                         if (++n >= 7) {
  493.                            out = put_binbyte(out,c & 0x7f);
  494.                            n = c = 0;
  495.                         }
  496.                     }
  497.                     if (n > 0)
  498.                        out = put_binbyte(out,c & 0x7f);
  499.                     break;
  500.  
  501.                case HCHR_UUEPKT:
  502.                     for ( ; len >= 3; in += 3, len -= 3) {
  503.                         *out++ = h_uuenc(in[0] >> 2);
  504.                         *out++ = h_uuenc(((in[0] << 4) & 0x30) | ((in[1] >> 4) & 0x0f));
  505.                         *out++ = h_uuenc(((in[1] << 2) & 0x3c) | ((in[2] >> 6) & 0x03));
  506.                         *out++ = h_uuenc(in[2] & 0x3f);
  507.                     }
  508.                     if (len > 0) {
  509.                        *out++ = h_uuenc(in[0] >> 2);
  510.                        *out++ = h_uuenc(((in[0] << 4) & 0x30) | ((in[1] >> 4) & 0x0f));
  511.                        if (len == 2)
  512.                           *out++ = h_uuenc((in[1] << 2) & 0x3c);
  513.                     }
  514.                     break;
  515.         }
  516.  
  517.         *out++ = H_DLE;
  518.         *out++ = HCHR_PKTEND;
  519.  
  520.         if (type != HPKT_DATA && format != HCHR_BINPKT) {
  521.            *out++ = '\r';
  522.            *out++ = '\n';
  523.         }
  524.  
  525.         for (in = (byte *) txpktprefix; *in; in++) {
  526.             switch (*in) {
  527.                    case 221: /* transmit break signal for one second */
  528.                              break;
  529.                    case 222: { h_timer t = h_timer_set(2);
  530.                                while (!h_timer_expired(t))
  531.                                      sys_idle();
  532.                              }
  533.                              break;
  534.                    case 223: com_putbyte(0);
  535.                              break;
  536.                    default:  com_putbyte(*in);
  537.                              break;
  538.             }
  539.         }
  540.  
  541.         com_putblock(txbuf,(word) (out - txbuf));
  542. }/*txpkt()*/
  543.  
  544.  
  545. /*---------------------------------------------------------------------------*/
  546. static int rxpkt (void)
  547. {
  548.         register byte *p, *q;
  549.         register int   c, n, i;
  550.  
  551.         if (keyabort())
  552.            return (H_SYSABORT);
  553.         if (!carrier())
  554.            return (H_CARRIER);
  555.  
  556.         p = rxbufptr;
  557.  
  558.         while ((c = com_getbyte()) >= 0) {
  559.               if (rxoptions & HOPT_HIGHBIT)
  560.                  c &= 0x7f;
  561.  
  562.               n = c;
  563.               if (rxoptions & HOPT_HIGHCTL)
  564.                  n &= 0x7f;
  565.               if (n != H_DLE &&
  566.                   (((rxoptions & HOPT_XONXOFF) && (n == XON || n == XOFF)) ||
  567.                    ((rxoptions & HOPT_CTLCHRS) && (n < 32 || n == 127))))
  568.                  continue;
  569.  
  570.               if (rxdle || c == H_DLE) {
  571.                  switch (c) {
  572.                         case H_DLE:
  573.                              if (++rxdle >= 5)
  574.                                 return (H_CANCEL);
  575.                              break;
  576.  
  577.                         case HCHR_PKTEND:
  578.                              rxbufptr = p;
  579.  
  580.                              switch (rxpktformat) {
  581.                                     case HCHR_BINPKT:
  582.                                          q = rxbufptr;
  583.                                          break;
  584.  
  585.                                     case HCHR_HEXPKT:
  586.                                          for (p = q = rxbuf; p < rxbufptr; p++) {
  587.                                              if (*p == '\\' && *++p != '\\') {
  588.                                                 i = *p;
  589.                                                 n = *++p;
  590.                                                 if ((i -= '0') > 9) i -= ('a' - ':');
  591.                                                 if ((n -= '0') > 9) n -= ('a' - ':');
  592.                                                 if ((i & ~0x0f) || (n & ~0x0f)) {
  593.                                                    i = H_NOPKT;
  594.                                                    break;
  595.                                                 }
  596.                                                 *q++ = (i << 4) | n;
  597.                                              }
  598.                                              else
  599.                                                 *q++ = *p;
  600.                                          }
  601.                                          if (p > rxbufptr)
  602.                                             c = H_NOPKT;
  603.                                          break;
  604.  
  605.                                     case HCHR_ASCPKT:
  606.                                          n = i = 0;
  607.                                          for (p = q = rxbuf; p < rxbufptr; p++) {
  608.                                              i |= ((*p & 0x7f) << n);
  609.                                              if ((n += 7) >= 8) {
  610.                                                 *q++ = (byte) (i & 0xff);
  611.                                                 i >>= 8;
  612.                                                 n -= 8;
  613.                                              }
  614.                                          }
  615.                                          break;
  616.  
  617.                                     case HCHR_UUEPKT:
  618.                                          n = (int) (rxbufptr - rxbuf);
  619.                                          for (p = q = rxbuf; n >= 4; n -= 4, p += 4) {
  620.                                              if (p[0] <= ' ' || p[0] >= 'a' ||
  621.                                                  p[1] <= ' ' || p[1] >= 'a' ||
  622.                                                  p[2] <= ' ' || p[2] >= 'a') {
  623.                                                 c = H_NOPKT;
  624.                                                 break;
  625.                                              }
  626.                                              *q++ = (byte) ((h_uudec(p[0]) << 2) | (h_uudec(p[1]) >> 4));
  627.                                              *q++ = (byte) ((h_uudec(p[1]) << 4) | (h_uudec(p[2]) >> 2));
  628.                                              *q++ = (byte) ((h_uudec(p[2]) << 6) | h_uudec(p[3]));
  629.                                          }
  630.                                          if (n >= 2) {
  631.                                             if (p[0] <= ' ' || p[0] >= 'a') {
  632.                                                c = H_NOPKT;
  633.                                                break;
  634.                                             }
  635.                                             *q++ = (byte) ((h_uudec(p[0]) << 2) | (h_uudec(p[1]) >> 4));
  636.                                             if (n == 3) {
  637.                                                if (p[0] <= ' ' || p[0] >= 'a') {
  638.                                                   c = H_NOPKT;
  639.                                                   break;
  640.                                                }
  641.                                                *q++ = (byte) ((h_uudec(p[1]) << 4) | (h_uudec(p[2]) >> 2));
  642.                                             }
  643.                                          }
  644.                                          break;
  645.  
  646.                                     default:   /* This'd mean internal fluke */
  647. #if H_DEBUG
  648. if (loglevel==0) {
  649.    message(0," <- <PKTEND> (pktformat='%c' dec=%d hex=%02x) ??",
  650.              rxpktformat, rxpktformat, rxpktformat);
  651. }
  652. #endif
  653.                                          c = H_NOPKT;
  654.                                          break;
  655.                              }
  656.  
  657.                              rxbufptr = NULL;
  658.  
  659.                              if (c == H_NOPKT)
  660.                                 break;
  661.  
  662.                              rxpktlen = (word) (q - rxbuf);
  663.                              if (rxpktformat != HCHR_HEXPKT && (rxoptions & HOPT_CRC32)) {
  664.                                 if (rxpktlen < 5) {
  665.                                    c = H_NOPKT;
  666.                                    break;
  667.                                 }
  668.                                 n = h_crc32test(crc32block(rxbuf,rxpktlen));
  669.                                 rxpktlen -= (int) sizeof (long);  /* remove CRC-32 */
  670.                              }
  671.                              else {
  672.                                 if (rxpktlen < 3) {
  673.                                    c = H_NOPKT;
  674.                                    break;
  675.                                 }
  676.                                 n = h_crc16test(crc16block(rxbuf,rxpktlen));
  677.                                 rxpktlen -= (int) sizeof (word);  /* remove CRC-16 */
  678.                              }
  679.  
  680.                              rxpktlen--;                     /* remove type  */
  681.  
  682.                              if (n) {
  683. #if H_DEBUG
  684. if (loglevel==0) {
  685.    char *s1, *s2, *s3, *s4;
  686.  
  687.    message(0," <- PKT (format='%c'  type='%c'  len=%d)",
  688.            rxpktformat, (int) rxbuf[rxpktlen], rxpktlen);
  689.  
  690.    switch (rxbuf[rxpktlen]) {
  691.           case HPKT_START:    message(0,"    START");
  692.                               break;
  693.           case HPKT_INIT:     s1 = ((char *) rxbuf) + ((int) strlen((char *) rxbuf)) + 1;
  694.                               s2 = s1 + ((int) strlen(s1)) + 1;
  695.                               s3 = s2 + ((int) strlen(s2)) + 1;
  696.                               s4 = s3 + ((int) strlen(s3)) + 1;
  697.                               message(0,"    INIT (appinfo='%s'  can='%s'  want='%s'  options='%s'  pktprefix='%s')",
  698.                                       (char *) rxbuf, s1, s2, s3, s4);
  699.                               break;
  700.           case HPKT_INITACK:  message(0,"    INITACK");
  701.                               break;
  702.           case HPKT_FINFO:    message(0,"    FINFO ('%s'  rxstate=%d)",rxbuf,rxstate);
  703.                               break;
  704.           case HPKT_FINFOACK: message(0,"    FINFOACK (pos=%ld  txstate=%d  txfd=%d)",
  705.                                       intell(h_long1(rxbuf)), txstate, txfd);
  706.                               break;
  707.           case HPKT_DATA:     message(0,"    DATA (rxstate=%d  pos=%ld  len=%u)",
  708.                                       rxstate, intell(h_long1(rxbuf)),
  709.                                       (word) (rxpktlen - ((int) sizeof (long))));
  710.                               break;
  711.           case HPKT_DATAACK:  message(0,"    DATAACK (rxstate=%d  pos=%ld)",
  712.                                       rxstate, intell(h_long1(rxbuf)));
  713.                               break;
  714.           case HPKT_RPOS:     message(0,"    RPOS (pos=%ld%s  blklen=%u->%ld  syncid=%ld%s  txstate=%d  txfd=%d)",
  715.                                       intell(h_long1(rxbuf)),
  716.                                       intell(h_long1(rxbuf)) < 0L ? " SKIP" : "",
  717.                                       txblklen, intell(h_long2(rxbuf)),
  718.                                       intell(h_long3(rxbuf)),
  719.                                       intell(h_long3(rxbuf)) == rxsyncid ? " DUP" : "",
  720.                                       txstate, txfd);
  721.                               break;
  722.           case HPKT_EOF:      message(0,"    EOF (rxstate=%d  pos=%ld%s)",
  723.                                       rxstate, intell(h_long1(rxbuf)),
  724.                                       intell(h_long1(rxbuf)) < 0L ? " SKIP" : "");
  725.                               break;
  726.           case HPKT_EOFACK:   message(0,"    EOFACK (txstate=%d)", txstate);
  727.                               break;
  728.           case HPKT_IDLE:     message(0,"    IDLE");
  729.                               break;
  730.           case HPKT_END:      message(0,"    END");
  731.                               break;
  732.           case HPKT_DEVDATA:  s1 = ((char *) rxbuf) + ((int) sizeof (long));
  733.                               message(0,"    DEVDATA (id=%ld  dev=%s  len=%u",
  734.                                       intell(h_long1(rxbuf)), s1,
  735.                                       rxpktlen - (((int) sizeof (long)) + ((int) strlen(s1)) + 1));
  736.                               break;
  737.           case HPKT_DEVDACK:  message(0,"    DEVDACK (devtxstate=%d  id=%ld)",
  738.                                       devtxstate, intell(h_long1(rxbuf)));
  739.                               break;
  740.           default:            message(0,"    Unkown pkttype %d (txstate=%d  rxstate=%d)",
  741.                                       (int) rxbuf[rxpktlen], txstate, rxstate);
  742.                               break;
  743.    }
  744. }
  745. #endif
  746.                                 return ((int) rxbuf[rxpktlen]);
  747.                              }/*goodpkt*/
  748.  
  749. #if H_DEBUG
  750. if (loglevel==0)
  751.    message(0," Bad CRC (format='%c'  type='%c'  len=%d)",
  752.              rxpktformat, (int) rxbuf[rxpktlen], rxpktlen);
  753. #endif
  754.                              break;
  755.  
  756.                         case HCHR_BINPKT: 
  757.                         case HCHR_HEXPKT: 
  758.                         case HCHR_ASCPKT: 
  759.                         case HCHR_UUEPKT:
  760. #if H_DEBUG
  761. if (loglevel==0)
  762.    message(0," <- <PKTSTART> (pktformat='%c')",c);
  763. #endif
  764.                              rxpktformat = c;
  765.                              p = rxbufptr = rxbuf;
  766.                              rxdle = 0;
  767.                              break;
  768.  
  769.                         default:
  770.                              if (p) {
  771.                                 if (p < rxbufmax)
  772.                                    *p++ = (byte) (c ^ 0x40);
  773.                                 else {
  774. #if H_DEBUG
  775. if (loglevel==0)
  776.    message(0," <- Pkt too long - discarded");
  777. #endif
  778.                                    p = NULL;
  779.                                 }
  780.                              }
  781.                              rxdle = 0;
  782.                              break;
  783.                  }
  784.               }
  785.               else if (p) {
  786.                  if (p < rxbufmax)
  787.                     *p++ = (byte) c;
  788.                  else {
  789. #if H_DEBUG
  790. if (loglevel==0)
  791.    message(0," <- Pkt too long - discarded");
  792. #endif
  793.                     p = NULL;
  794.                  }
  795.               }
  796.         }
  797.  
  798.         rxbufptr = p;
  799.  
  800.         if (h_timer_running(braindead) && h_timer_expired(braindead)) {
  801. #if H_DEBUG
  802. if (loglevel==0)
  803.    message(0," <- BrainDead (timer=%08lx  time=%08lx)",
  804.            braindead,time(NULL));
  805. #endif
  806.            return (H_BRAINTIME);
  807.         }
  808.         if (h_timer_running(txtimer) && h_timer_expired(txtimer)) {
  809. #if H_DEBUG
  810. if (loglevel==0)
  811.    message(0," <- TxTimer (timer=%08lx  time=%08lx)",
  812.            txtimer,time(NULL));
  813. #endif
  814.            return (H_TXTIME);
  815.         }
  816.         if (h_timer_running(devtxtimer) && h_timer_expired(devtxtimer)) {
  817. #if H_DEBUG
  818. if (loglevel==0)
  819.    message(0," <- DevTxTimer (timer=%08lx  time=%08lx)",
  820.            devtxtimer,time(NULL));
  821. #endif
  822.            return (H_DEVTXTIME);
  823.         }
  824.  
  825.         sys_idle();
  826.         return (H_NOPKT);
  827. }/*rxpkt()*/
  828.  
  829.  
  830. /*---------------------------------------------------------------------------*/
  831. static void hydra_status (boolean xmit)
  832. {
  833.         long pos    = xmit ? txpos    : rxpos,
  834.              fsize  = xmit ? txfsize  : rxfsize;
  835.  
  836.         hydra_gotoxy(46,xmit ? 1 : 2);
  837.         if (pos >= fsize)
  838.            hydra_printf("%ld/%ld (EOF)",pos,fsize);
  839.         else {
  840.            int left = (int) ((((fsize - pos) / 128L) * 1340L) / cur_speed);
  841.            char *p = "";
  842.  
  843.            if (xmit) {
  844.               if      (txstate == HTX_DATAACK) p = "ACK ";
  845.               else if (txstate == HTX_XWAIT)   p = "WAIT ";
  846.            }
  847.            hydra_printf("%ld/%ld (%s%d:%02d min left)",
  848.                         pos, fsize, p, left / 60, left % 60);
  849.         }
  850.         hydra_clreol();
  851. }/*hydra_status()*/
  852.  
  853.  
  854. /*---------------------------------------------------------------------------*/
  855. static void hydra_pct (boolean xmit)
  856. {
  857.         long offset = xmit ? txoffset : rxoffset,
  858.              fsize  = xmit ? txfsize  : rxfsize,
  859.              start  = xmit ? txstart  : rxstart,
  860.              elapsed, bytes, cps, pct;
  861.  
  862.         elapsed = time(NULL) - start;
  863.         bytes = fsize - offset;
  864.         if (bytes < 1024L || elapsed == 0L)
  865.            return;
  866.         cps = bytes / elapsed;
  867.         pct = (cps * 1000L) / ((long) cur_speed);
  868.         message(2,"+%s-H CPS: %ld (%ld bytes), %d:%02d min.  Eff: %ld%%",
  869.                 xmit ? "Sent" : "Rcvd", cps, bytes,
  870.                 (int) (elapsed / 60), (int) (elapsed % 60), pct);
  871. }/*hydra_pct()*/
  872.  
  873.  
  874. /*---------------------------------------------------------------------------*/
  875. void hydra_badxfer (void)
  876. {
  877.         if (rxfd >= 0) {
  878.            dos_close(rxfd);
  879.            rxfd = -1;
  880.            if (xfer_bad())
  881.               message(1,"+HRECV: Bad xfer recovery-info saved");
  882.            else
  883.               message(0,"-HRECV: Bad xfer - file deleted");
  884.         }
  885. }/*hydra_badxfer()*/
  886.  
  887.  
  888. /*---------------------------------------------------------------------------*/
  889. void hydra_init (dword want_options)
  890. {
  891.         register word i, j;
  892.         word  crc16;
  893.         dword crc32;
  894.  
  895.         txbuf    = (byte *)  malloc(H_BUFLEN);
  896.         rxbuf    = (byte *)  malloc(H_BUFLEN);
  897.         crc16tab = (word *)  malloc(256 * ((int) sizeof (word)));
  898.         crc32tab = (dword *) malloc(256 * ((int) sizeof (dword)));
  899.         if (!txbuf || !rxbuf || !crc16tab || !crc32tab) {
  900.            message(6,"!HYDRA: Can't allocate buffers!");
  901.            endprog(2);
  902.         }
  903.         txbufin  = txbuf + ((H_MAXBLKLEN + H_OVERHEAD + 5) * 2);
  904.         rxbufmax = rxbuf + H_MAXPKTLEN;
  905.  
  906.         for (i = 0; i < 256; i++) {
  907.             crc16 = i;
  908.             crc32 = i;
  909.             for (j = 8; j > 0; j--) {
  910.                 if (crc16 & 1) crc16 = (crc16 >> 1) ^ h_crc16poly;
  911.                 else           crc16 >>= 1;
  912.                 if (crc32 & 1) crc32 = (crc32 >> 1) ^ h_crc32poly;
  913.                 else           crc32 >>= 1;
  914.             }
  915.             crc16tab[i] = crc16;
  916.             crc32tab[i] = crc32;
  917.         }
  918.  
  919.         batchesdone = 0;
  920.  
  921.         originator = nooriginator ? false : true;
  922.  
  923.         if (originator)
  924.            hdxlink = false;
  925.         else if (hdxsession)
  926.            hdxlink = true;
  927.  
  928.         options = (want_options & HCAN_OPTIONS) & ~HUNN_OPTIONS;
  929.  
  930.         timeout = (word) (40960L / cur_speed);
  931.         if      (timeout < H_MINTIMER) timeout = H_MINTIMER;
  932.         else if (timeout > H_MAXTIMER) timeout = H_MAXTIMER;
  933.  
  934.         txmaxblklen = (cur_speed / 300) * 128;
  935.         if      (txmaxblklen < 256)         txmaxblklen = 256;
  936.         else if (txmaxblklen > H_MAXBLKLEN) txmaxblklen = H_MAXBLKLEN;
  937.  
  938.         rxblklen = txblklen = (cur_speed < 2400U) ? 256 : 512;
  939.  
  940.         txgoodbytes  = 0;
  941.         txgoodneeded = 1024;
  942.  
  943.         txstate = HTX_DONE;
  944.  
  945.         if (!mailer)
  946.            message(-1,"+HYDRA session (%s-directional mode)",
  947.                       hdxlink ? "Uni" : "Bi");
  948.  
  949. #if WIN_AGL
  950. { byte ev   = win_maxver - 25,          /* extra lines available vertically? */
  951.        elog = ev / 3,                   /* 1/3 of extra lines for log_win    */
  952.        eloc = ev / 3,                   /* 1/3 of extra lines for local_win  */
  953.        erem = ev - (elog + eloc);       /* the rest is extra for remote_win  */
  954.  
  955.         log_win = win_create(1, 1, win_maxhor, 6 + elog,
  956.                               CUR_NONE, CON_RAW | CON_WRAP | CON_SCROLL,
  957.                               CHR_NORMAL, KEY_RAW);
  958.         win_setattrib(log_win,CHR_INVERSE);
  959.         win_clreol(log_win);
  960.         win_printf(log_win," %s v%s - COPYRIGHT (C) 1991-1993 A.G.Lentz, LENTZ SOFTWARE-DEVELOPMENT",PRGNAME,VERSION);
  961.         win_setattrib(log_win,CHR_NORMAL);
  962.         win_setrange(log_win,1,2,win_maxhor,6 + elog);
  963.  
  964.         file_win = win_create(1, 7 + elog, win_maxhor, 9 + elog,
  965.                               CUR_NONE, CON_RAW, CHR_NORMAL, KEY_RAW);
  966.         win_setattrib(file_win,CHR_INVERSE);
  967.         win_clreol(file_win);
  968.         win_printf(file_win," Port=%u   ComSpeed=%u   LineSpeed=%u",
  969.                             port + 1, com_speed, cur_speed);
  970.         win_xyputs(file_win,48,1,"Press ESC to abort Hydra session");
  971.         win_setattrib(file_win,CHR_F_YELLOW);
  972.         win_xyputs(file_win,2,2,"Sending  :");
  973.         win_xyputs(file_win,2,3,"Receiving:");
  974.         win_setattrib(file_win,CHR_NORMAL);
  975.         win_setrange(file_win,1,2,win_maxhor,3);
  976.  
  977.         remote_win = win_create(1, 10 + elog, win_maxhor, 17 + elog + erem,
  978.                                 CUR_NONE, CON_COOKED | CON_WRAP | CON_SCROLL,
  979.                                 CHR_NORMAL, KEY_RAW);
  980.         win_setattrib(remote_win,CHR_INVERSE);
  981.         win_fill(remote_win,177);
  982.         win_puts(remote_win," Remote ");
  983.         win_setattrib(remote_win,CHR_NORMAL);
  984.         win_setrange(remote_win,1,2,win_maxhor,8 + erem);
  985.         win_cls(remote_win);
  986.  
  987.         local_win = win_create(1, 18 + elog + erem, win_maxhor, win_maxver,
  988.                                CUR_NORMAL, CON_COOKED | CON_WRAP | CON_SCROLL,
  989.                                CHR_NORMAL, KEY_RAW);
  990.         win_setattrib(local_win,CHR_INVERSE);
  991.         win_fill(local_win,177);
  992.         win_puts(local_win," Local (Press Alt-C to start/end chat mode) ");
  993.         win_setattrib(local_win,CHR_NORMAL);
  994.         win_setrange(local_win,1,2,win_maxhor,8 + eloc);
  995.         win_cls(local_win);
  996.  
  997.         log_first = false;
  998.  
  999.         win_settop(log_win);
  1000.         win_settop(file_win);
  1001.         win_settop(remote_win);
  1002.         win_settop(local_win);
  1003. }
  1004. #elif defined(AMIGA)
  1005. /* */
  1006. #else
  1007. { struct text_info ti;
  1008.  
  1009.         term_x = wherex();
  1010.         term_y = wherey();
  1011.         gettextinfo(&ti);
  1012.         window(1,1,ti.screenwidth,ti.screenheight);
  1013.         term_scr = malloc(ti.screenwidth * ti.screenheight * sizeof (word));
  1014.         gettext(1,1,ti.screenwidth,ti.screenheight,term_scr);
  1015.  
  1016.         clrscr();
  1017.         textbackground(LIGHTGRAY);
  1018.         textcolor(BLACK);
  1019.  
  1020.         gotoxy(1,1);
  1021.         clreol();
  1022.         cprintf(" %s v%s - COPYRIGHT (C) 1991-1993 A.G.Lentz, LENTZ SOFTWARE-DEVELOPMENT",PRGNAME,VERSION);
  1023.  
  1024.         gotoxy(1,7);
  1025.         clreol();
  1026.         cprintf(" Port=%u   ComSpeed=%u   LineSpeed=%u",
  1027.                 port + 1, com_speed, cur_speed);
  1028.         gotoxy(48,7);
  1029.         cprintf("Press ESC to abort Hydra session");
  1030.  
  1031.         gotoxy(1,10);
  1032.         for (i = 0; i < ti.screenwidth; i++) putch(177);
  1033.         gotoxy(1,10);
  1034.         cprintf(" Remote ");
  1035.  
  1036.         gotoxy(1,18);
  1037.         for (i = 0; i < ti.screenwidth; i++) putch(177);
  1038.         gotoxy(1,18);
  1039.         cprintf(" Local (Press Alt-C to start/end chat mode) ");
  1040.  
  1041.         textbackground(BLACK);
  1042.         textcolor(YELLOW);
  1043.         gotoxy(2,8);
  1044.         cprintf("Sending  :");
  1045.         gotoxy(2,9);
  1046.         cprintf("Receiving:");
  1047.  
  1048.         window(1,19,80,25);
  1049.         textcolor(LIGHTGRAY);
  1050.         file_x = file_y = remote_x = remote_y = local_x = local_y = 1;
  1051.         log_y = 0;
  1052. }
  1053. #endif
  1054.  
  1055.         hydra_devfunc("CON",rem_chat);
  1056.  
  1057.         chatfill  = 0;
  1058.         chattimer = -1L;
  1059.         lasttimer = 0L;
  1060.  
  1061.         message(2,"+HYDRA session (%s-directional mode)",
  1062.                   hdxlink ? "Uni" : "Bi");
  1063. }/*hydra_init()*/
  1064.  
  1065.  
  1066. /*---------------------------------------------------------------------------*/
  1067. void hydra_deinit (void)
  1068. {
  1069. #if WIN_AGL
  1070.         win_settop(0);
  1071.         win_close(file_win);
  1072.         win_close(log_win);
  1073.         win_close(remote_win);
  1074.         win_close(local_win);
  1075.         file_win = 0;
  1076. #elif defined(AMIGA)
  1077. /* */
  1078. #else
  1079. { struct text_info ti;
  1080.  
  1081.         gettextinfo(&ti);
  1082.         window(1,1,ti.screenwidth,ti.screenheight);
  1083.         puttext(1,1,ti.screenwidth,ti.screenheight,term_scr);
  1084.         gotoxy(term_x,term_y);
  1085.         free(term_scr);
  1086.         file_x = 0;
  1087. }
  1088. #endif
  1089.  
  1090.         free(txbuf);
  1091.         free(rxbuf);
  1092.         free(crc16tab);
  1093.         free(crc32tab);
  1094. }/*hydra_deinit()*/
  1095.  
  1096.  
  1097. /*---------------------------------------------------------------------------*/
  1098. int hydra (char *txpathname, char *txalias)
  1099. {
  1100.         int   res;
  1101.         int   pkttype;
  1102.         char *p, *q;
  1103.         int   i;
  1104.         struct stat f;
  1105.  
  1106.         /*-------------------------------------------------------------------*/
  1107.         if (txstate == HTX_DONE) {
  1108.            txstate        = HTX_START;
  1109.            hydra_gotoxy(13,1);
  1110.            hydra_printf("Init");
  1111.            txoptions      = HTXI_OPTIONS;
  1112.            txpktprefix[0] = '\0';
  1113.  
  1114.            rxstate   = HRX_INIT;
  1115.            hydra_gotoxy(13,2);
  1116.            hydra_printf("Init");
  1117.            rxoptions = HRXI_OPTIONS;
  1118.            rxfd      = -1;
  1119.            rxdle     = 0;
  1120.            rxbufptr  = NULL;
  1121.            rxtimer   = h_timer_reset();
  1122.  
  1123.            devtxid    = devrxid = 0L;
  1124.            devtxtimer = h_timer_reset();
  1125.            devtxstate = HTD_DONE;
  1126.  
  1127.            braindead = h_timer_set(H_BRAINDEAD);
  1128.         }
  1129.         else
  1130.            txstate = HTX_FINFO;
  1131.  
  1132.         txtimer   = h_timer_reset();
  1133.         txretries = 0;
  1134.  
  1135.         /*-------------------------------------------------------------------*/
  1136.         if (txpathname) {
  1137.            stat(txpathname,&f);
  1138.            txfsize = f.st_size;
  1139.            txftime = f.st_mtime;
  1140.  
  1141.            if ((txfd = dos_sopen(txpathname,0)) < 0) {
  1142.               message(3,"-HSEND: Unable to open %s",txpathname);
  1143.               return (XFER_SKIP);
  1144.            }
  1145.  
  1146. #ifdef AMIGA
  1147.            strcpy(txfname,FilePart(txpathname));
  1148. #else
  1149.            strupr(txpathname);
  1150.            for (p=txpathname, q=txfname; *p; p++) {
  1151.                if (*q=*p, *p=='\\' || *p==':' || *p=='/')
  1152.                   q=txfname;
  1153.                else q++;
  1154.            }
  1155.            *q = '\0';
  1156.  
  1157.            if (txalias)
  1158.               strupr(txalias);
  1159. #endif    /* AMIGA */
  1160.  
  1161.            txstart  = 0L;
  1162.            txsyncid = 0L;
  1163.         }
  1164.         else {
  1165.            txfd = -1;
  1166.            strcpy(txfname,"");
  1167.         }
  1168.  
  1169.         /*-------------------------------------------------------------------*/
  1170.         do {
  1171.            /*----------------------------------------------------------------*/
  1172.            switch (devtxstate) {
  1173.                   /*---------------------------------------------------------*/
  1174.                   case HTD_DATA:
  1175.                        if (txstate > HTX_RINIT) {
  1176.                           h_long1(txbufin) = intell(devtxid);
  1177.                           p = ((char *) txbufin) + ((int) sizeof(long));
  1178.                           strcpy(p,devtxdev);
  1179.                           p += H_FLAGLEN + 1;
  1180.                           memcpy(p,devtxbuf,devtxlen);
  1181.                           txpkt(((int) sizeof (long)) + H_FLAGLEN + 1 + devtxlen,HPKT_DEVDATA);
  1182.                           devtxtimer = h_timer_set(timeout);
  1183.                           devtxstate = HTD_DACK;
  1184.                        }
  1185.                        break;
  1186.  
  1187.                   /*---------------------------------------------------------*/
  1188.                   default:
  1189.                        break;
  1190.  
  1191.                   /*---------------------------------------------------------*/
  1192.            }
  1193.  
  1194.            /*----------------------------------------------------------------*/
  1195.            switch (txstate) {
  1196.                   /*---------------------------------------------------------*/
  1197.                   case HTX_START:
  1198.                        com_putblock((byte *) autostr,(int) strlen(autostr));
  1199.                        txpkt(0,HPKT_START);
  1200.                        txtimer = h_timer_set(H_START);
  1201.                        txstate = HTX_SWAIT;
  1202.                        break;
  1203.  
  1204.                   /*---------------------------------------------------------*/
  1205.                   case HTX_INIT:
  1206.                        p = (char *) txbufin;
  1207.                        sprintf(p,"%08lx%s,%s %s",
  1208.                                  H_REVSTAMP,PRGNAME,VERSION,HC_OS);
  1209.                        p += ((int) strlen(p)) + 1;/* our app info & HYDRA rev. */
  1210.                        put_flags(p,h_flags,HCAN_OPTIONS);    /* what we CAN  */
  1211.                        p += ((int) strlen(p)) + 1;
  1212.                        put_flags(p,h_flags,options);         /* what we WANT */
  1213.                        p += ((int) strlen(p)) + 1;
  1214.                        sprintf(p,"%08lx%08lx",               /* TxRx windows */
  1215.                                  hydra_txwindow,hydra_rxwindow);
  1216.                        p += ((int) strlen(p)) + 1;
  1217.                        strcpy(p,pktprefix);     /* pkt prefix string we want */
  1218.                        p += ((int) strlen(p)) + 1;
  1219.  
  1220.                        txoptions = HTXI_OPTIONS;
  1221.                        txpkt((word) (((byte *) p) - txbufin), HPKT_INIT);
  1222.                        txoptions = rxoptions;
  1223.                        txtimer = h_timer_set(timeout / 2);
  1224.                        txstate = HTX_INITACK;
  1225.                        break;
  1226.  
  1227.                   /*---------------------------------------------------------*/
  1228.                   case HTX_FINFO:
  1229.                        if (txfd >= 0) {
  1230.                           if (!txretries) {
  1231.                              hydra_gotoxy(13,1);
  1232.                              hydra_printf(txfname);
  1233.                              if (txalias) {
  1234.                                 hydra_gotoxy(25,1);
  1235.                                 hydra_printf("  ->  %s",txalias);
  1236.                              }
  1237.                              hydra_clreol();
  1238.                              message(2,"+HSEND: %s%s%s (%ldb), %d min.",
  1239.                                      txpathname, txalias ? " -> " : "", txalias ? txalias : "",
  1240.                                      txfsize, (int) (txfsize * 10L / cur_speed + 27L) / 54L);
  1241.  
  1242.                              strlwr(txfname);
  1243.                           }
  1244.                           sprintf((char *) txbufin,"%08lx%08lx%08lx%08lx%08lx%s",
  1245.                                   txftime, txfsize, 0L, 0L, 0L,
  1246.                                   txalias ? txalias : txfname);
  1247.                        }
  1248.                        else {
  1249.                           if (!txretries) {
  1250.                              hydra_gotoxy(13,1);
  1251.                              hydra_printf("End of batch");
  1252.                              hydra_clreol();
  1253.                              message(1,"+HSEND: End of batch");
  1254.                           }
  1255.                           strcpy((char *) txbufin,txfname);
  1256.                        }
  1257.                        txpkt(((int) strlen((char *) txbufin)) + 1,HPKT_FINFO);
  1258.                        txtimer = h_timer_set(txretries ? timeout / 2 : timeout);
  1259.                        txstate = HTX_FINFOACK;
  1260.                        break;
  1261.  
  1262.                   /*---------------------------------------------------------*/
  1263.                   case HTX_XDATA:
  1264.                        if (com_outfull() > txmaxblklen)
  1265.                           break;
  1266.  
  1267.                        if (txpos < 0L)
  1268.                           i = -1;                                    /* Skip */
  1269.                        else {
  1270.                           h_long1(txbufin) = intell(txpos);
  1271.                           if ((i = dos_read(txfd,txbufin + ((int) sizeof (long)),txblklen)) < 0) {
  1272.                              message(6,"!HSEND: File read error");
  1273.                              dos_close(txfd);
  1274.                              txfd = -1;
  1275.                              txpos = -2L;                            /* Skip */
  1276.                           }
  1277.                        }
  1278.  
  1279.                        if (i > 0) {
  1280.                           txpos += i;
  1281.                           txpkt(((int) sizeof (long)) + i, HPKT_DATA);
  1282.  
  1283.                           if (txblklen < txmaxblklen &&
  1284.                               (txgoodbytes += i) >= txgoodneeded) {
  1285.                              txblklen <<= 1;
  1286.                              if (txblklen >= txmaxblklen) {
  1287.                                 txblklen = txmaxblklen;
  1288.                                 txgoodneeded = 0;
  1289.                              }
  1290.                              txgoodbytes = 0;
  1291.                           }
  1292.  
  1293.                           if (txwindow && (txpos >= (txlastack + txwindow))) {
  1294.                              txtimer = h_timer_set(txretries ? timeout / 2 : timeout);
  1295.                              txstate = HTX_DATAACK;
  1296.                           }
  1297.  
  1298.                           if (!txstart)
  1299.                              txstart = time(NULL);
  1300.                           hydra_status(true);
  1301.                           break;
  1302.                        }
  1303.  
  1304.                        /* fallthrough to HTX_EOF */
  1305.  
  1306.                   /*---------------------------------------------------------*/
  1307.                   case HTX_EOF:
  1308.                        h_long1(txbufin) = intell(txpos);
  1309.                        txpkt((int) sizeof (long),HPKT_EOF);
  1310.                        txtimer = h_timer_set(txretries ? timeout / 2 : timeout);
  1311.                        txstate = HTX_EOFACK;
  1312.                        break;
  1313.  
  1314.                   /*---------------------------------------------------------*/
  1315.                   case HTX_END:
  1316.                        txpkt(0,HPKT_END);
  1317.                        txpkt(0,HPKT_END);
  1318.                        txtimer = h_timer_set(timeout / 2);
  1319.                        txstate = HTX_ENDACK;
  1320.                        break;
  1321.  
  1322.                   /*---------------------------------------------------------*/
  1323.                   default:
  1324.                        break;
  1325.  
  1326.                   /*---------------------------------------------------------*/
  1327.            }
  1328.  
  1329.            /*----------------------------------------------------------------*/
  1330.            while (txstate && (pkttype = rxpkt()) != H_NOPKT) {
  1331.                  /*----------------------------------------------------------*/
  1332.                  switch (pkttype) {
  1333.                         /*---------------------------------------------------*/
  1334.                         case H_CARRIER:
  1335.                         case H_CANCEL:
  1336.                         case H_SYSABORT:
  1337.                         case H_BRAINTIME:
  1338.                              switch (pkttype) {
  1339.                                     case H_CARRIER:   p = "Carrier lost";          break;
  1340.                                     case H_CANCEL:    p = "Aborted by other side"; break;
  1341.                                     case H_SYSABORT:  p = "Aborted by operator";   break;
  1342.                                     case H_BRAINTIME: p = "Other end died";        break;
  1343.                              }
  1344.                              message(3,"-HYDRA: %s",p);
  1345.                              txstate = HTX_DONE;
  1346.                              res = XFER_ABORT;
  1347.                              break;
  1348.  
  1349.                         /*---------------------------------------------------*/
  1350.                         case H_TXTIME:
  1351.                              if (txstate == HTX_XWAIT || txstate == HTX_REND) {
  1352.                                 txpkt(0,HPKT_IDLE);
  1353.                                 txtimer = h_timer_set(H_IDLE);
  1354.                                 break;
  1355.                              }
  1356.  
  1357.                              if (++txretries > H_RETRIES) {
  1358.                                 message(3,"-HSEND: Too many errors");
  1359.                                 txstate = HTX_DONE;
  1360.                                 res = XFER_ABORT;
  1361.                                 break;
  1362.                              }
  1363.  
  1364.                              message(0,"-HSEND: Timeout - Retry %u",txretries);
  1365.  
  1366.                              txtimer = h_timer_reset();
  1367.  
  1368.                              switch (txstate) {
  1369.                                     case HTX_SWAIT:    txstate = HTX_START; break;
  1370.                                     case HTX_INITACK:  txstate = HTX_INIT;  break;
  1371.                                     case HTX_FINFOACK: txstate = HTX_FINFO; break;
  1372.                                     case HTX_DATAACK:  txstate = HTX_XDATA; break;
  1373.                                     case HTX_EOFACK:   txstate = HTX_EOF;   break;
  1374.                                     case HTX_ENDACK:   txstate = HTX_END;   break;
  1375.                              }
  1376.                              break;
  1377.  
  1378.                         /*---------------------------------------------------*/
  1379.                         case H_DEVTXTIME:
  1380.                              if (++devtxretries > H_RETRIES) {
  1381.                                 message(3,"-HDEVTX: Too many errors");
  1382.                                 txstate = HTX_DONE;
  1383.                                 res = XFER_ABORT;
  1384.                                 break;
  1385.                              }
  1386.  
  1387.                              message(0,"-HDEVTX: Timeout - Retry %u",devtxretries);
  1388.  
  1389.                              devtxtimer = h_timer_reset();
  1390.                              devtxstate = HTD_DATA;
  1391.                              break;
  1392.  
  1393.                         /*---------------------------------------------------*/
  1394.                         case HPKT_START:
  1395.                              if (txstate == HTX_START || txstate == HTX_SWAIT) {
  1396.                                 txtimer = h_timer_reset();
  1397.                                 txretries = 0;
  1398.                                 txstate = HTX_INIT;
  1399.                                 braindead = h_timer_set(H_BRAINDEAD);
  1400.                              }
  1401.                              break;
  1402.  
  1403.                         /*---------------------------------------------------*/
  1404.                         case HPKT_INIT:
  1405.                              if (rxstate == HRX_INIT) {
  1406.                                 p = (char *) rxbuf;
  1407.                                 p += ((int) strlen(p)) + 1;
  1408.                                 q = p + ((int) strlen(p)) + 1;
  1409.                                 rxoptions  = options | HUNN_OPTIONS;
  1410.                                 rxoptions |= get_flags(q,h_flags);
  1411.                                 rxoptions &= get_flags(p,h_flags);
  1412.                                 rxoptions &= HCAN_OPTIONS;
  1413.                                 if (rxoptions < (options & HNEC_OPTIONS)) {
  1414.                                    message(6,"!HYDRA: Incompatible on this link");
  1415.                                    txstate = HTX_DONE;
  1416.                                    res = XFER_ABORT;
  1417.                                    break;
  1418.                                 }
  1419.                                 p = q + ((int) strlen(q)) + 1;
  1420.                                 rxwindow = txwindow = 0L;
  1421.                                 sscanf(p,"%08lx%08lx", &rxwindow,&txwindow);
  1422.                                 if (rxwindow < 0L) rxwindow = 0L;
  1423.                                 if (hydra_rxwindow &&
  1424.                                     (!rxwindow || hydra_rxwindow < rxwindow))
  1425.                                    rxwindow = hydra_rxwindow;
  1426.                                 if (txwindow < 0L) txwindow = 0L;
  1427.                                 if (hydra_txwindow &&
  1428.                                     (!txwindow || hydra_txwindow < txwindow))
  1429.                                    txwindow = hydra_txwindow;
  1430.                                 p += ((int) strlen(p)) + 1;
  1431.                                 strncpy(txpktprefix,p,H_PKTPREFIX);
  1432.                                 txpktprefix[H_PKTPREFIX] = '\0';
  1433.  
  1434.                                 if (!batchesdone) {
  1435.                                    long revstamp;
  1436.  
  1437.                                    p = (char *) rxbuf;
  1438.                                    sscanf(p,"%08lx",&revstamp);
  1439.                                    message(0,"*HYDRA: Other's HydraRev=%s",
  1440.                                            h_revdate(revstamp));
  1441.                                    p += 8;
  1442.                                    if ((q = strchr(p,',')) != NULL) *q = ' ';
  1443.                                    if ((q = strchr(p,',')) != NULL) *q = '/';
  1444.                                    message(0,"*HYDRA: Other's App.Info '%s'",p);
  1445.                                    put_flags((char *) rxbuf,h_flags,rxoptions);
  1446.                                    message(1,"*HYDRA: Using link options '%s'",rxbuf);
  1447.                                    if (txwindow || rxwindow)
  1448.                                       message(0,"*HYDRA: Window tx=%ld rx=%ld",
  1449.                                                 txwindow,rxwindow);
  1450.                                 }
  1451.  
  1452.                                 chattimer = (rxoptions & HOPT_DEVICE) ? 0L : -2L;
  1453.  
  1454.                                 txoptions = rxoptions;
  1455.                                 rxstate = HRX_FINFO;
  1456.                              }
  1457.  
  1458.                              txpkt(0,HPKT_INITACK);
  1459.                              break;
  1460.  
  1461.                         /*---------------------------------------------------*/
  1462.                         case HPKT_INITACK:
  1463.                              if (txstate == HTX_INIT || txstate == HTX_INITACK) {
  1464.                                 braindead = h_timer_set(H_BRAINDEAD);
  1465.                                 txtimer = h_timer_reset();
  1466.                                 txretries = 0;
  1467.                                 txstate = HTX_RINIT;
  1468.                              }
  1469.                              break;
  1470.  
  1471.                         /*---------------------------------------------------*/
  1472.                         case HPKT_FINFO:
  1473.                              if (rxstate == HRX_FINFO) {
  1474.                                 braindead = h_timer_set(H_BRAINDEAD);
  1475.                                 if (!rxbuf[0]) {
  1476.                                    hydra_gotoxy(13,2);
  1477.                                    hydra_printf("End of batch");
  1478.                                    hydra_clreol();
  1479.                                    message(1,"*HRECV: End of batch");
  1480.                                    rxpos = 0L;
  1481.                                    rxstate = HRX_DONE;
  1482.                                    batchesdone++;
  1483.                                 }
  1484.                                 else {
  1485.                                    long diskfree;
  1486.  
  1487.                                    rxfsize = rxftime = 0L;
  1488.                                    rxfname[0] = '\0';
  1489.                                    sscanf((char *) rxbuf,"%08lx%08lx%*08lx%*08lx%*08lx%s",
  1490.                                           &rxftime, &rxfsize, rxfname);
  1491. #ifndef AMIGA
  1492.                                    strupr(rxfname);
  1493. #endif    /* AMIGA */
  1494.                                    hydra_gotoxy(13,2);
  1495.                                    hydra_printf(rxfname);
  1496.                                    hydra_clreol();
  1497.  
  1498.                                    rxpathname = xfer_init(rxfname,rxfsize,rxftime);
  1499.  
  1500.                                    diskfree = freespace(rxpathname);
  1501.  
  1502.                                    if (!rxpathname) {   /* Already have file */
  1503.                                       if (single_done) {
  1504.                                          hydra_gotoxy(29,2);
  1505.                                          hydra_printf("Skipping additional files");
  1506.                                          message(1,"+HRECV: Skipping additional files (file %s)",rxfname);
  1507.                                          rxpos = -2L;
  1508.                                       }
  1509.                                       else {
  1510.                                          hydra_gotoxy(29,2);
  1511.                                          hydra_printf("Already have file");
  1512.                                          message(1,"+HRECV: Already have %s",rxfname);
  1513.                                          rxpos = -1L;
  1514.                                       }
  1515.                                    }
  1516.                                    else if (rxfsize + 10240L > diskfree) {
  1517.                                       hydra_gotoxy(29,2);
  1518.                                       hydra_printf("Not enough diskspace");
  1519.                                       message(6,"!HRECV: %s not enough diskspace: %ld > %ld",
  1520.                                               rxfname, rxfsize + 10240L, diskfree);
  1521.                                       rxpos = -2L;
  1522.                                    }
  1523.                                    else {
  1524.                                       if (fexist(rxpathname)) { /* Resuming? */
  1525.                                          if ((rxfd = dos_sopen(rxpathname,0)) < 0) {
  1526.                                             message(6,"!HRECV: Unable to re-open %s",rxpathname);
  1527.                                             rxpos = -2L;
  1528.                                          }
  1529.                                       }
  1530.                                       else if ((rxfd = dos_sopen(rxpathname,1)) < 0) {
  1531.                                          message(6,"!HRECV: Unable to create %s",rxpathname);
  1532.                                          rxpos = -2L;
  1533.                                       }
  1534.  
  1535.                                       if (rxfd >= 0) {
  1536.                                          message(2,"+HRECV: %s (%ldb), %d min.",
  1537.                                                  rxfname, rxfsize,
  1538.                                                  (int) (rxfsize * 10L / cur_speed + 27L) / 54L);
  1539.                                          if (dos_seek(rxfd,0L,SEEK_END) < 0L) {
  1540.                                             message(6,"!HRECV: File seek error");
  1541.                                             hydra_badxfer();
  1542.                                             rxpos = -2L;
  1543.                                          }
  1544.                                          else {
  1545.                                             rxoffset = rxpos = dos_tell(rxfd);
  1546.                                             if (rxpos < 0L) {
  1547.                                                message(6,"!HRECV: File tell error");
  1548.                                                hydra_badxfer();
  1549.                                                rxpos = -2L;
  1550.                                             }
  1551.                                             else {
  1552.                                                rxstart = 0L;
  1553.                                                rxtimer = h_timer_reset();
  1554.                                                rxretries = 0;
  1555.                                                rxlastsync = 0L;
  1556.                                                rxsyncid = 0L;
  1557.                                                hydra_status(false);
  1558.                                                if (rxpos > 0L) {
  1559.                                                   hydra_gotoxy(46,2);
  1560.                                                   hydra_printf("%ld/%ld",rxpos,rxfsize);
  1561.                                                   message(1,"+HRECV: Resuming from offset %ld (%d min. to go)",
  1562.                                                           rxpos, (int) ((rxfsize - rxoffset) * 10L / cur_speed + 27L) / 54L);
  1563.                                                }
  1564.                                                rxstate = HRX_DATA;
  1565.                                             }
  1566.                                          }
  1567.                                       }
  1568.                                    }
  1569.                                 }
  1570.                              }
  1571.                              else if (rxstate == HRX_DONE)
  1572.                                 rxpos = (!rxbuf[0]) ? 0L : -2L;
  1573.  
  1574.                              h_long1(txbufin) = intell(rxpos);
  1575.                              txpkt((int) sizeof (long),HPKT_FINFOACK);
  1576.                              break;
  1577.  
  1578.                         /*---------------------------------------------------*/
  1579.                         case HPKT_FINFOACK:
  1580.                              if (txstate == HTX_FINFO || txstate == HTX_FINFOACK) {
  1581.                                 braindead = h_timer_set(H_BRAINDEAD);
  1582.                                 txretries = 0;
  1583.                                 if (!txfname[0]) {
  1584.                                    txtimer = h_timer_set(H_IDLE);
  1585.                                    txstate = HTX_REND;
  1586.                                 }
  1587.                                 else {
  1588.                                    txtimer = h_timer_reset();
  1589.                                    txpos = intell(h_long1(rxbuf));
  1590.                                    if (txpos >= 0L) {
  1591.                                       txoffset = txpos;
  1592.                                       txlastack = txpos;
  1593.                                       hydra_status(true);
  1594.                                       if (txpos > 0L) {
  1595.                                          message(1,"+HSEND: Transmitting from offset %ld (%d min. to go)",
  1596.                                                  txpos, (int) ((txfsize - txoffset) * 10L / cur_speed + 27L) / 54L);
  1597.                                          if (dos_seek(txfd,txpos,SEEK_SET) < 0L) {
  1598.                                             message(6,"!HSEND: File seek error");
  1599.                                             dos_close(txfd);
  1600.                                             txfd = -1;
  1601.                                             txpos = -2L;
  1602.                                             txstate = HTX_EOF;
  1603.                                             break;
  1604.                                          }
  1605.                                       }
  1606.                                       txstate = HTX_XDATA;
  1607.                                    }
  1608.                                    else {
  1609.                                       dos_close(txfd);
  1610.                                       if (txpos == -1L) {
  1611.                                          hydra_gotoxy(29,1);
  1612.                                          hydra_printf("They already have file");
  1613.                                          message(1,"+HSEND: They already have %s",txfname);
  1614.                                          if (mailer)
  1615.                                             resultlog(true,txpathname,txfsize,0L);
  1616.                                          return (XFER_OK);
  1617.                                       }
  1618.                                       else {  /* (txpos < -1L) file NOT sent */
  1619.                                          hydra_gotoxy(29,1);
  1620.                                          hydra_printf("Skipping");
  1621.                                          message(1,"+HSEND: Skipping %s",txfname);
  1622.                                          return (XFER_SKIP);
  1623.                                       }
  1624.                                    }
  1625.                                 }
  1626.                              }
  1627.                              break;
  1628.  
  1629.                         /*---------------------------------------------------*/
  1630.                         case HPKT_DATA:
  1631.                              if (rxstate == HRX_DATA) {
  1632.                                 if (intell(h_long1(rxbuf)) != rxpos ||
  1633.                                     intell(h_long1(rxbuf)) < 0L) {
  1634.                                    if (intell(h_long1(rxbuf)) <= rxlastsync) {
  1635.                                       rxtimer = h_timer_reset();
  1636.                                       rxretries = 0;
  1637.                                    }
  1638.                                    rxlastsync = intell(h_long1(rxbuf));
  1639.  
  1640.                                    if (!h_timer_running(rxtimer) ||
  1641.                                        h_timer_expired(rxtimer)) {
  1642.                                       if (rxretries > 4) {
  1643.                                          if (txstate < HTX_REND &&
  1644.                                              !originator && !hdxlink) {
  1645.                                             hdxlink = true;
  1646.                                             rxretries = 0;
  1647.                                          }
  1648.                                       }
  1649.                                       if (++rxretries > H_RETRIES) {
  1650.                                          message(3,"-HRECV: Too many errors");
  1651.                                          txstate = HTX_DONE;
  1652.                                          res = XFER_ABORT;
  1653.                                          break;
  1654.                                       }
  1655.                                       if (rxretries == 1)
  1656.                                          rxsyncid++;
  1657.  
  1658.                                       rxblklen /= 2;
  1659.                                       i = rxblklen;
  1660.                                       if      (i <=  64) i =   64;
  1661.                                       else if (i <= 128) i =  128;
  1662.                                       else if (i <= 256) i =  256;
  1663.                                       else if (i <= 512) i =  512;
  1664.                                       else               i = 1024;
  1665.                                       message(0,"-HRECV: Bad pkt at %ld - Retry %u (newblklen=%u)",
  1666.                                               rxpos,rxretries,i);
  1667.                                       h_long1(txbufin) = intell(rxpos);
  1668.                                       h_long2(txbufin) = intell((long) i);
  1669.                                       h_long3(txbufin) = intell(rxsyncid);
  1670.                                       txpkt(3 * ((int) sizeof(long)),HPKT_RPOS);
  1671.                                       rxtimer = h_timer_set(timeout);
  1672.                                    }
  1673.                                 }
  1674.                                 else {
  1675.                                    braindead = h_timer_set(H_BRAINDEAD);
  1676.                                    rxpktlen -= (int) sizeof (long);
  1677.                                    rxblklen = rxpktlen;
  1678.                                    if (dos_write(rxfd,rxbuf + ((int) sizeof (long)),rxpktlen) < 0) {
  1679.                                       message(6,"!HRECV: File write error");
  1680.                                       hydra_badxfer();
  1681.                                       rxpos = -2L;
  1682.                                       rxretries = 1;
  1683.                                       rxsyncid++;
  1684.                                       h_long1(txbufin) = intell(rxpos);
  1685.                                       h_long2(txbufin) = intell(0L);
  1686.                                       h_long3(txbufin) = intell(rxsyncid);
  1687.                                       txpkt(3 * ((int) sizeof(long)),HPKT_RPOS);
  1688.                                       rxtimer = h_timer_set(timeout);
  1689.                                       break;
  1690.                                    }
  1691.                                    rxretries = 0;
  1692.                                    rxtimer = h_timer_reset();
  1693.                                    rxlastsync = rxpos;
  1694.                                    rxpos += rxpktlen;
  1695.                                    if (rxwindow) {
  1696.                                       h_long1(txbufin) = intell(rxpos);
  1697.                                       txpkt((int) sizeof(long),HPKT_DATAACK);
  1698.                                    }
  1699.                                    if (!rxstart)
  1700.                                       rxstart = time(NULL) -
  1701.                                                 ((rxpktlen * 10) / cur_speed);
  1702.                                    hydra_status(false);
  1703.                                 }/*badpkt*/
  1704.                              }/*rxstate==HRX_DATA*/
  1705.                              break;
  1706.  
  1707.                         /*---------------------------------------------------*/
  1708.                         case HPKT_DATAACK:
  1709.                              if (txstate == HTX_XDATA || txstate == HTX_DATAACK ||
  1710.                                  txstate == HTX_XWAIT ||
  1711.                                  txstate == HTX_EOF || txstate == HTX_EOFACK) {
  1712.                                 if (txwindow && intell(h_long1(rxbuf)) > txlastack) {
  1713.                                    txlastack = intell(h_long1(rxbuf));
  1714.                                    if (txstate == HTX_DATAACK &&
  1715.                                        (txpos < (txlastack + txwindow))) {
  1716.                                       txstate = HTX_XDATA;
  1717.                                       txretries = 0;
  1718.                                       txtimer = h_timer_reset();
  1719.                                    }
  1720.                                 }
  1721.                              }
  1722.                              break;
  1723.  
  1724.                         /*---------------------------------------------------*/
  1725.                         case HPKT_RPOS:
  1726.                              if (txstate == HTX_XDATA || txstate == HTX_DATAACK ||
  1727.                                  txstate == HTX_XWAIT ||
  1728.                                  txstate == HTX_EOF || txstate == HTX_EOFACK) {
  1729.                                 if (intell(h_long3(rxbuf)) != txsyncid) {
  1730.                                    txsyncid = intell(h_long3(rxbuf));
  1731.                                    txretries = 1;
  1732.                                    txtimer = h_timer_reset();
  1733.                                    txpos = intell(h_long1(rxbuf));
  1734.                                    if (txpos < 0L) {
  1735.                                       if (txfd >= 0) {
  1736.                                          hydra_gotoxy(29,1);
  1737.                                          hydra_printf("Skipping");
  1738.                                          message(1,"+HSEND: Skipping %s",txfname);
  1739.                                          dos_close(txfd);
  1740.                                          txfd = -1;
  1741.                                          txstate = HTX_EOF;
  1742.                                       }
  1743.                                       txpos = -2L;
  1744.                                       break;
  1745.                                    }
  1746.  
  1747.                                    if (txblklen > intell(h_long2(rxbuf)))
  1748.                                       txblklen = (word) intell(h_long2(rxbuf));
  1749.                                    else
  1750.                                       txblklen >>= 1;
  1751.                                    if      (txblklen <=  64) txblklen =   64;
  1752.                                    else if (txblklen <= 128) txblklen =  128;
  1753.                                    else if (txblklen <= 256) txblklen =  256;
  1754.                                    else if (txblklen <= 512) txblklen =  512;
  1755.                                    else                      txblklen = 1024;
  1756.                                    txgoodbytes = 0;
  1757.                                    txgoodneeded += 1024;
  1758.                                    if (txgoodneeded > 8192)
  1759.                                       txgoodneeded = 8192;
  1760.  
  1761.                                    hydra_status(true);
  1762.                                    message(0,"+HSEND: Resending from offset %ld (newblklen=%u)",
  1763.                                            txpos,txblklen);
  1764.                                    if (dos_seek(txfd,txpos,SEEK_SET) < 0L) {
  1765.                                       message(6,"!HSEND: File seek error");
  1766.                                       dos_close(txfd);
  1767.                                       txfd = -1;
  1768.                                       txpos = -2L;
  1769.                                       txstate = HTX_EOF;
  1770.                                       break;
  1771.                                    }
  1772.  
  1773.                                    if (txstate != HTX_XWAIT)
  1774.                                       txstate = HTX_XDATA;
  1775.                                 }
  1776.                                 else {
  1777.                                    if (++txretries > H_RETRIES) {
  1778.                                       message(3,"-HSEND: Too many errors");
  1779.                                       txstate = HTX_DONE;
  1780.                                       res = XFER_ABORT;
  1781.                                       break;
  1782.                                    }
  1783.                                 }
  1784.                              }
  1785.                              break;
  1786.  
  1787.                         /*---------------------------------------------------*/
  1788.                         case HPKT_EOF:
  1789.                              if (rxstate == HRX_DATA) {
  1790.                                 if (intell(h_long1(rxbuf)) < 0L) {
  1791.                                    hydra_badxfer();
  1792.                                    hydra_gotoxy(29,2);
  1793.                                    hydra_printf("Skipping");
  1794.                                    hydra_clreol();
  1795.                                    message(1,"+HRECV: Skipping %s",rxfname);
  1796.                                    rxstate = HRX_FINFO;
  1797.                                    braindead = h_timer_set(H_BRAINDEAD);
  1798.                                 }
  1799.                                 else if (intell(h_long1(rxbuf)) != rxpos) {
  1800.                                    if (intell(h_long1(rxbuf)) <= rxlastsync) {
  1801.                                       rxtimer = h_timer_reset();
  1802.                                       rxretries = 0;
  1803.                                    }
  1804.                                    rxlastsync = intell(h_long1(rxbuf));
  1805.  
  1806.                                    if (!h_timer_running(rxtimer) ||
  1807.                                        h_timer_expired(rxtimer)) {
  1808.                                       if (++rxretries > H_RETRIES) {
  1809.                                          message(3,"-HRECV: Too many errors");
  1810.                                          txstate = HTX_DONE;
  1811.                                          res = XFER_ABORT;
  1812.                                          break;
  1813.                                       }
  1814.                                       if (rxretries == 1)
  1815.                                          rxsyncid++;
  1816.  
  1817.                                       rxblklen /= 2;
  1818.                                       i = rxblklen;
  1819.                                       if      (i <=  64) i =   64;
  1820.                                       else if (i <= 128) i =  128;
  1821.                                       else if (i <= 256) i =  256;
  1822.                                       else if (i <= 512) i =  512;
  1823.                                       else               i = 1024;
  1824.                                       message(0,"-HRECV: Bad EOF at %ld - Retry %u (newblklen=%u)",
  1825.                                               rxpos,rxretries,i);
  1826.                                       h_long1(txbufin) = intell(rxpos);
  1827.                                       h_long2(txbufin) = intell((long) i);
  1828.                                       h_long3(txbufin) = intell(rxsyncid);
  1829.                                       txpkt(3 * ((int) sizeof(long)),HPKT_RPOS);
  1830.                                       rxtimer = h_timer_set(timeout);
  1831.                                    }
  1832.                                 }
  1833.                                 else {
  1834.                                    rxfsize = rxpos;
  1835.                                    dos_close(rxfd);
  1836.                                    rxfd = -1;
  1837.                                    hydra_pct(false);
  1838.  
  1839.                                    p = xfer_okay();
  1840.                                    if (p) {
  1841.                                       hydra_gotoxy(25,2);
  1842.                                       hydra_printf("  -> %s",p);
  1843.                                       message(1,"+HRECV: Dup file renamed: %s",p);
  1844.                                    }
  1845.  
  1846.                                    hydra_status(false);
  1847.                                    message(1,"+Rcvd-H %s",p ? p : rxfname);
  1848.                                    resultlog(false,p ? p : rxfname,rxfsize - rxoffset,time(NULL) - rxstart);
  1849.                                    rxstate = HRX_FINFO;
  1850.                                    braindead = h_timer_set(H_BRAINDEAD);
  1851.                                 }/*skip/badeof/eof*/
  1852.                              }/*rxstate==HRX_DATA*/
  1853.  
  1854.                              if (rxstate == HRX_FINFO)
  1855.                                 txpkt(0,HPKT_EOFACK);
  1856.                              break;
  1857.  
  1858.                         /*---------------------------------------------------*/
  1859.                         case HPKT_EOFACK:
  1860.                              if (txstate == HTX_EOF || txstate == HTX_EOFACK) {
  1861.                                 braindead = h_timer_set(H_BRAINDEAD);
  1862.                                 if (txfd >= 0) {
  1863.                                    txfsize = txpos;
  1864.                                    dos_close(txfd);
  1865.                                    hydra_pct(true);
  1866.                                    resultlog(true,txpathname,txfsize - txoffset,time(NULL) - txstart);
  1867.                                    return (XFER_OK);
  1868.                                 }
  1869.                                 else
  1870.                                    return (XFER_SKIP);
  1871.                              }
  1872.                              break;
  1873.  
  1874.                         /*---------------------------------------------------*/
  1875.                         case HPKT_IDLE:
  1876.                              if (txstate == HTX_XWAIT) {
  1877.                                 hdxlink = false;
  1878.                                 txtimer = h_timer_reset();
  1879.                                 txretries = 0;
  1880.                                 txstate = HTX_XDATA;
  1881.                              }
  1882.                              else if (txstate >= HTX_FINFO && txstate < HTX_REND)
  1883.                                 braindead = h_timer_set(H_BRAINDEAD);
  1884.                              break;
  1885.  
  1886.                         /*---------------------------------------------------*/
  1887.                         case HPKT_END:
  1888.                              /* special for chat, other side wants to quit */
  1889.                              if (chattimer > 0L && txstate == HTX_REND) {
  1890.                                 chattimer = -3L;
  1891.                                 break;
  1892.                              }
  1893.  
  1894.                              if (txstate == HTX_END || txstate == HTX_ENDACK) {
  1895.                                 txpkt(0,HPKT_END);
  1896.                                 txpkt(0,HPKT_END);
  1897.                                 txpkt(0,HPKT_END);
  1898.                                 message(1,"+HYDRA: Completed");
  1899.                                 txstate = HTX_DONE;
  1900.                                 res = XFER_OK;
  1901.                              }
  1902.                              break;
  1903.  
  1904.                         /*---------------------------------------------------*/
  1905.                         case HPKT_DEVDATA:
  1906.                              if (devrxid != intell(h_long1(rxbuf))) {
  1907.                                 hydra_devrecv();
  1908.                                 devrxid = intell(h_long1(rxbuf));
  1909.                              }
  1910.                              h_long1(txbufin) = intell(devrxid);
  1911.                              txpkt((int) sizeof (long),HPKT_DEVDACK);
  1912.                              break;
  1913.  
  1914.                         /*---------------------------------------------------*/
  1915.                         case HPKT_DEVDACK:
  1916.                              if (devtxstate && (devtxid == intell(h_long1(rxbuf)))) {
  1917.                                 devtxtimer = h_timer_reset();
  1918.                                 devtxstate = HTD_DONE;
  1919.                              }
  1920.                              break;
  1921.  
  1922.                         /*---------------------------------------------------*/
  1923.                         default:  /* unknown packet types: IGNORE, no error! */
  1924.                              break;
  1925.  
  1926.                         /*---------------------------------------------------*/
  1927.                  }/*switch(pkttype)*/
  1928.  
  1929.                  /*----------------------------------------------------------*/
  1930.                  switch (txstate) {
  1931.                         /*---------------------------------------------------*/
  1932.                         case HTX_START:
  1933.                         case HTX_SWAIT:
  1934.                              if (rxstate == HRX_FINFO) {
  1935.                                 txtimer = h_timer_reset();
  1936.                                 txretries = 0;
  1937.                                 txstate = HTX_INIT;
  1938.                              }
  1939.                              break;
  1940.  
  1941.                         /*---------------------------------------------------*/
  1942.                         case HTX_RINIT:
  1943.                              if (rxstate == HRX_FINFO) {
  1944.                                 txtimer = h_timer_reset();
  1945.                                 txretries = 0;
  1946.                                 txstate = HTX_FINFO;
  1947.                              }
  1948.                              break;
  1949.  
  1950.                         /*---------------------------------------------------*/
  1951.                         case HTX_XDATA:
  1952.                              if (rxstate && hdxlink) {
  1953.                                 message(3,"*HYDRA: %s",hdxmsg);
  1954.                                 hydra_devsend("MSG",(byte *) hdxmsg,(int) strlen(hdxmsg));
  1955.  
  1956.                                 txtimer = h_timer_set(H_IDLE);
  1957.                                 txstate = HTX_XWAIT;
  1958.                              }
  1959.                              break;
  1960.  
  1961.                         /*---------------------------------------------------*/
  1962.                         case HTX_XWAIT:
  1963.                              if (!rxstate) {
  1964.                                 txtimer = h_timer_reset();
  1965.                                 txretries = 0;
  1966.                                 txstate = HTX_XDATA;
  1967.                              }
  1968.                              break;
  1969.  
  1970.                         /*---------------------------------------------------*/
  1971.                         case HTX_REND:
  1972.                              if (!rxstate && !devtxstate) {
  1973.                                 /* special for chat, braindead will protect */
  1974.                                 if (chattimer > 0L) break;
  1975.                                 if (chattimer == 0L) chattimer = -3L;
  1976.  
  1977.                                 txtimer = h_timer_reset();
  1978.                                 txretries = 0;
  1979.                                 txstate = HTX_END;
  1980.                              }
  1981.                              break;
  1982.  
  1983.                         /*---------------------------------------------------*/
  1984.                  }/*switch(txstate)*/
  1985.            }/*while(txstate&&pkttype)*/
  1986.         } while (txstate);
  1987.  
  1988.         if (txfd >= 0)
  1989.            dos_close(txfd);
  1990.         hydra_badxfer();
  1991.  
  1992.         if (res == XFER_ABORT) {
  1993.            com_dump();
  1994.            if (carrier()) {
  1995.               com_putblock((byte *) abortstr,(int) strlen(abortstr));
  1996.               com_flush();
  1997.            }
  1998.            com_purge();
  1999.         }
  2000.         else
  2001.            com_flush();
  2002.  
  2003.         return (res);
  2004. }/*hydra()*/
  2005.  
  2006.  
  2007. /* end of hydra.c */
  2008.